iT邦幫忙

2025 iThome 鐵人賽

DAY 30
0

前言

前一回,透過 main.tf 去管理 AWS Lambda Function,這些資源關注的是有沒有配置合適的權限,讓程式碼片段運行起來,所以重點會在 Policy 和 Lambda Source 的維護。 即使拆掉重建,也不會影響太大。
然而,像是 API Gateway 這種資源,建立起來後要綁憑證,然後串後端,不會一言不合就拆掉重建。 今天會接著看如何透過 Terraform 去維護既有的資源。

另外因為我們目前雲上已經有既存的 Lambda Function,如果要加入 Terraform 的話,分成兩個不同的狀態作法不同:

  1. 未來新加入的功能 -> 直接加料到 terraform
  2. 已經存在的功能 -> 走 import 方式進入管理

terraform import aws_lambda_function.list_vlog_videos list-vlog-videos

改寫流程

確認欲納管的 API Gateway 資源

  • 使用 AWS CLI 抓取
aws apigatewayv2 get-apis
  • 回傳內容
{
    "Items": [
        {
            "ApiEndpoint": "https://iwlw3i3ys4.execute-api.ap-northeast-1.amazonaws.com",
            "ApiId": "iwlw3i3ys4",
            "ApiKeySelectionExpression": "$request.header.x-api-key",
            "CorsConfiguration": {
                "AllowCredentials": false,
                "AllowHeaders": [
                    "content-type",
                    "authorization"
                ],
                "AllowMethods": [
                    "GET",
                    "POST",
                    "OPTIONS",
                    "DELETE"
                ],
                "AllowOrigins": [
                    "https://vlog.nipapa.tw"
                ],
                "MaxAge": 3600
            },
            "CreatedDate": "2025-09-18T15:32:42+00:00",
            "DisableExecuteApiEndpoint": false,
            "IpAddressType": "ipv4",
            "Name": "exsky-vlog-api",
            "ProtocolType": "HTTP",
            "RouteSelectionExpression": "$request.method $request.path",
            "Tags": {}
        }
    ]
}
  • 提取其中
    • ApiId:iwlw3i3ys4
    • Stage name
  • 修改 main.tf 中 API Gateway 段落,建立對應的空殼資源(不要建立新的)。
# 既有 API Gateway(使用 import 接手)
resource "aws_apigatewayv2_api" "vlog_api" {
  name          = "exsky-vlog-api"
  protocol_type = "HTTP"

  cors_configuration {
    allow_credentials = false
    allow_headers     = ["content-type", "authorization"]
    allow_methods     = ["GET", "POST", "OPTIONS", "DELETE"]
    allow_origins     = ["https://vlog.nipapa.tw"]
    max_age           = 3600
  }
}
  • 這樣 Terraform 只會知道有這個資源,不會建立新的。
  • 接續下列指令,讓上述宣告資源
❯ terraform import aws_apigatewayv2_api.vlog_api iwlw3i3ys4

# 回傳結果
aws_apigatewayv2_api.vlog_api: Importing from ID "iwlw3i3ys4"...
aws_apigatewayv2_api.vlog_api: Import prepared!
  Prepared aws_apigatewayv2_api for import
aws_apigatewayv2_api.vlog_api: Refreshing state... [id=iwlw3i3ys4]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
  • 驗證狀態
terraform state list
  • 產生計劃
terraform plan

將 stage 納管

  • 新增下列片段 ... (前一回已經加入)
resource "aws_apigatewayv2_stage" "prod" {
  api_id      = aws_apigatewayv2_api.vlog_api.id
  name        = "prod"
  auto_deploy = true
}
  • 加入計劃
terraform import aws_apigatewayv2_stage.prod iwlw3i3ys4/prod

將 route 納管

  • 先查 APIG (api gateway 的縮寫) 的路由,因為輸出資料很常,所以把它先寫進檔案,再打開來看會比較方便。
aws apigatewayv2 get-routes --api-id iwlw3i3ys4 > apig_route.json

vim apig_route.json
  • 總共 14 條
{
    "Items": [
        {
            "ApiKeyRequired": false,
            "AuthorizationType": "NONE",
            "RouteId": "3w1zksi",
            "RouteKey": "ANY /generate-subtitle",
            "Target": "integrations/61f7rhi"
        },
        {
            "ApiKeyRequired": false,
            "AuthorizationType": "NONE",
            "RouteId": "54cts80",
            "RouteKey": "GET /validate",
            "Target": "integrations/n6017vl"
        },
        {
            "ApiKeyRequired": false,
            "AuthorizationType": "NONE",
            "RouteId": "69zs0d3",
            "RouteKey": "ANY /forgot-password",
            "Target": "integrations/3r138kq"
        },
        {
            "ApiKeyRequired": false,
            "AuthorizationType": "NONE",
            "RouteId": "6ipuix8",
            "RouteKey": "ANY /verify-email",
            "Target": "integrations/lp5cg47"
        },
        {
            "ApiKeyRequired": false,
            "AuthorizationType": "NONE",
            "RouteId": "6yvrgw8",
            "RouteKey": "ANY /register",
            "Target": "integrations/aukb6gm"
        },
        {
            "ApiKeyRequired": false,
            "AuthorizationType": "NONE",
            "RouteId": "aujel9k",
            "RouteKey": "ANY /delete-video",
            "Target": "integrations/06oofh4"
        },
        {
            "ApiKeyRequired": false,
            "AuthorizationType": "NONE",
            "RouteId": "c8knbva",
            "RouteKey": "POST /login",
            "Target": "integrations/a1zfsfc"
        },
        {
            "ApiKeyRequired": false,
            "AuthorizationType": "NONE",
            "RouteId": "cnc53jm",
            "RouteKey": "ANY /generate-url",
            "Target": "integrations/xjq72ut"
        },
        {
            "ApiKeyRequired": false,
            "AuthorizationType": "NONE",
            "RouteId": "ij9mprm",
            "RouteKey": "ANY /reels",
            "Target": "integrations/rw7vivp"
        },
        {
            "ApiKeyRequired": false,
            "AuthorizationType": "NONE",
            "RouteId": "im5rhy3",
            "RouteKey": "ANY /convert-mov-to-mp4",
            "Target": "integrations/dm3ly76"
        },
        {
            "ApiKeyRequired": false,
            "AuthorizationType": "NONE",
            "RouteId": "n38wucu",
            "RouteKey": "GET /login",
            "Target": "integrations/wilhzsq"
        },
        {
            "ApiKeyRequired": false,
            "AuthorizationType": "NONE",
            "RouteId": "r6orxqr",
            "RouteKey": "ANY /reset-password",
            "Target": "integrations/eycavyc"
        },
        {
            "ApiKeyRequired": false,
            "AuthorizationType": "NONE",
            "RouteId": "s0t9834",
            "RouteKey": "ANY /list-subtitles",
            "Target": "integrations/9e4atgf"
        },
        {
            "ApiKeyRequired": false,
            "AuthorizationType": "NONE",
            "RouteId": "v0xhl3v",
            "RouteKey": "ANY /list-videos",
            "Target": "integrations/9804ssj"
        }
    ]
}
  • 用指令檢查 apig 的 integration
aws apigatewayv2 get-integrations --api-id iwlw3i3ys4
  • 輸出結果如下
{
    "Items": [
        {
            "ConnectionType": "INTERNET",
            "IntegrationId": "06oofh4",
            "IntegrationMethod": "POST",
            "IntegrationType": "AWS_PROXY",
            "IntegrationUri": "arn:aws:lambda:ap-northeast-1:<你的_AWS_ID>:function:delete-vlog-video",
            "PayloadFormatVersion": "2.0",
            "TimeoutInMillis": 30000
        },
        {
            "ConnectionType": "INTERNET",
            "IntegrationId": "3r138kq",
            "IntegrationMethod": "POST",
            "IntegrationType": "AWS_PROXY",
            "IntegrationUri": "arn:aws:lambda:ap-northeast-1:<你的_AWS_ID>:function:forgot-vlog-password",
            "PayloadFormatVersion": "2.0",
            "TimeoutInMillis": 30000
        },
        {
            "ConnectionType": "INTERNET",
            "IntegrationId": "61f7rhi",
            "IntegrationMethod": "POST",
            "IntegrationType": "AWS_PROXY",
            "IntegrationUri": "arn:aws:lambda:ap-northeast-1:<你的_AWS_ID>:function:generate-vlog-subtitle",
            "PayloadFormatVersion": "2.0",
            "TimeoutInMillis": 30000
        },
        {
            "ConnectionType": "INTERNET",
            "IntegrationId": "9804ssj",
            "IntegrationMethod": "POST",
            "IntegrationType": "AWS_PROXY",
            "IntegrationUri": "arn:aws:lambda:ap-northeast-1:<你的_AWS_ID>:function:list-vlog-videos",
            "PayloadFormatVersion": "2.0",
            "TimeoutInMillis": 30000
        },
        {
            "ConnectionType": "INTERNET",
            "IntegrationId": "9e4atgf",
            "IntegrationMethod": "POST",
            "IntegrationType": "AWS_PROXY",
            "IntegrationUri": "arn:aws:lambda:ap-northeast-1:<你的_AWS_ID>:function:list-vlog-subtitles",
            "PayloadFormatVersion": "2.0",
            "TimeoutInMillis": 30000
        },
        {
            "ConnectionType": "INTERNET",
            "IntegrationId": "a1zfsfc",
            "IntegrationMethod": "POST",
            "IntegrationType": "AWS_PROXY",
            "IntegrationUri": "arn:aws:lambda:ap-northeast-1:<你的_AWS_ID>:function:login-vlog-member",
            "PayloadFormatVersion": "2.0",
            "TimeoutInMillis": 30000
        },
        {
            "ConnectionType": "INTERNET",
            "IntegrationId": "aukb6gm",
            "IntegrationMethod": "POST",
            "IntegrationType": "AWS_PROXY",
            "IntegrationUri": "arn:aws:lambda:ap-northeast-1:<你的_AWS_ID>:function:register-vlog-member",
            "PayloadFormatVersion": "2.0",
            "TimeoutInMillis": 30000
        },
        {
            "ConnectionType": "INTERNET",
            "IntegrationId": "dm3ly76",
            "IntegrationMethod": "POST",
            "IntegrationType": "AWS_PROXY",
            "IntegrationUri": "arn:aws:lambda:ap-northeast-1:<你的_AWS_ID>:function:convert-vlog-mov-to-mp4",
            "PayloadFormatVersion": "2.0",
            "TimeoutInMillis": 30000
        },
        {
            "ConnectionType": "INTERNET",
            "IntegrationId": "eycavyc",
            "IntegrationMethod": "POST",
            "IntegrationType": "AWS_PROXY",
            "IntegrationUri": "arn:aws:lambda:ap-northeast-1:<你的_AWS_ID>:function:reset-vlog-password",
            "PayloadFormatVersion": "2.0",
            "TimeoutInMillis": 30000
        },
        {
            "ConnectionType": "INTERNET",
            "IntegrationId": "lp5cg47",
            "IntegrationMethod": "POST",
            "IntegrationType": "AWS_PROXY",
            "IntegrationUri": "arn:aws:lambda:ap-northeast-1:<你的_AWS_ID>:function:verify-vlog-email",
            "PayloadFormatVersion": "2.0",
            "TimeoutInMillis": 30000
        },
        {
            "ConnectionType": "INTERNET",
            "IntegrationId": "n6017vl",
            "IntegrationMethod": "POST",
            "IntegrationType": "AWS_PROXY",
            "IntegrationUri": "arn:aws:lambda:ap-northeast-1:<你的_AWS_ID>:function:validate-vlog-member",
            "PayloadFormatVersion": "2.0",
            "TimeoutInMillis": 30000
        },
        {
            "ConnectionType": "INTERNET",
            "IntegrationId": "rw7vivp",
            "IntegrationMethod": "POST",
            "IntegrationType": "AWS_PROXY",
            "IntegrationUri": "arn:aws:lambda:ap-northeast-1:<你的_AWS_ID>:function:prompt-vlog-reel",
            "PayloadFormatVersion": "2.0",
            "TimeoutInMillis": 30000
        },
        {
            "ConnectionType": "INTERNET",
            "IntegrationId": "wilhzsq",
            "IntegrationMethod": "GET",
            "IntegrationType": "HTTP_PROXY",
            "IntegrationUri": "https://vlog.nipapa.tw/login.html",
            "PayloadFormatVersion": "1.0",
            "TimeoutInMillis": 30000
        },
        {
            "ConnectionType": "INTERNET",
            "IntegrationId": "xjq72ut",
            "IntegrationMethod": "POST",
            "IntegrationType": "AWS_PROXY",
            "IntegrationUri": "arn:aws:lambda:ap-northeast-1:<你的_AWS_ID>:function:generate-vlog-s3-presigned-url",
            "PayloadFormatVersion": "2.0",
            "TimeoutInMillis": 30000
        }
    ]
}
  • 修改 main.tf 一條 Integration 接著一條 Route
# 🔹 Route 對應 Lambda Integration
resource "aws_apigatewayv2_integration" "list_videos" {
  api_id                 = aws_apigatewayv2_api.vlog_api.id
  integration_type       = "AWS_PROXY"
  integration_uri        = "arn:aws:lambda:ap-northeast-1:<你的_AWS_ID>:function:list-vlog-videos"
  payload_format_version = "2.0"
}

resource "aws_apigatewayv2_route" "list_videos_route" {
  api_id    = aws_apigatewayv2_api.vlog_api.id
  route_key = "GET /list-videos"
  target    = "integrations/${aws_apigatewayv2_integration.list_videos.id}"
}

最後 main.tf 如下

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }

  required_version = ">= 1.5.0"
}

provider "aws" {
  region = "ap-northeast-1"
}

# 🔹 IAM Role for Lambda
resource "aws_iam_role" "lambda_exec" {
  name = "lambda-execution-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect = "Allow"
      Principal = { Service = "lambda.amazonaws.com" }
      Action = "sts:AssumeRole"
    }]
  })
}

# 🔹 IAM Policy 附加 (讓 Lambda 能使用 S3 / DynamoDB / SES)
resource "aws_iam_role_policy" "lambda_policy" {
  name = "lambda-execution-policy"
  role = aws_iam_role.lambda_exec.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Action = [
          "logs:*",
          "s3:*",
          "dynamodb:*",
          "ses:SendEmail"
        ],
        Resource = "*"
      }
    ]
  })
}

# 🔹 Lambda Function (list-vlog-videos)
resource "aws_lambda_function" "list_vlog_videos" {
  function_name = "list-vlog-videos"
  role          = aws_iam_role.lambda_exec.arn
  handler       = "main.lambda_handler"
  runtime       = "python3.13"

  filename         = "lambda/list-vlog-videos.zip"
  source_code_hash = filebase64sha256("lambda/list-vlog-videos.zip")

  environment {
    variables = {
      BUCKET_NAME = "exsky-backup-media"
      JWT_SECRET  = "mysecret"
    }
  }
}

# 🔹 API Gateway (HTTP API)
resource "aws_apigatewayv2_api" "vlog_api" {
  name          = "exsky-vlog-api"
  protocol_type = "HTTP"

  cors_configuration {
    allow_credentials = false
    allow_headers     = ["content-type", "authorization"]
    allow_methods     = ["GET", "POST", "OPTIONS", "DELETE"]
    allow_origins     = ["https://vlog.nipapa.tw"]
    max_age           = 3600
  }
}

####################################
# ✅ 各 Lambda 整合 (Integration)
####################################
resource "aws_apigatewayv2_integration" "generate_subtitle" {
  api_id                 = aws_apigatewayv2_api.vlog_api.id
  integration_type       = "AWS_PROXY"
  integration_uri        = "arn:aws:lambda:ap-northeast-1:<你的AWD_ID>:function:generate-vlog-subtitle"
  payload_format_version = "2.0"
}

resource "aws_apigatewayv2_integration" "list_videos" {
  api_id                 = aws_apigatewayv2_api.vlog_api.id
  integration_type       = "AWS_PROXY"
  integration_uri        = "arn:aws:lambda:ap-northeast-1:<你的AWD_ID>:function:list-vlog-videos"
  payload_format_version = "2.0"
}

resource "aws_apigatewayv2_integration" "register_member" {
  api_id                 = aws_apigatewayv2_api.vlog_api.id
  integration_type       = "AWS_PROXY"
  integration_uri        = "arn:aws:lambda:ap-northeast-1:<你的AWD_ID>:function:register-vlog-member"
  payload_format_version = "2.0"
}

resource "aws_apigatewayv2_integration" "login_member" {
  api_id                 = aws_apigatewayv2_api.vlog_api.id
  integration_type       = "AWS_PROXY"
  integration_uri        = "arn:aws:lambda:ap-northeast-1:<你的AWD_ID>:function:login-vlog-member"
  payload_format_version = "2.0"
}

resource "aws_apigatewayv2_integration" "verify_email" {
  api_id                 = aws_apigatewayv2_api.vlog_api.id
  integration_type       = "AWS_PROXY"
  integration_uri        = "arn:aws:lambda:ap-northeast-1:<你的AWD_ID>:function:verify-vlog-email"
  payload_format_version = "2.0"
}

resource "aws_apigatewayv2_integration" "reset_password" {
  api_id                 = aws_apigatewayv2_api.vlog_api.id
  integration_type       = "AWS_PROXY"
  integration_uri        = "arn:aws:lambda:ap-northeast-1:<你的AWD_ID>:function:reset-vlog-password"
  payload_format_version = "2.0"
}

resource "aws_apigatewayv2_integration" "forgot_password" {
  api_id                 = aws_apigatewayv2_api.vlog_api.id
  integration_type       = "AWS_PROXY"
  integration_uri        = "arn:aws:lambda:ap-northeast-1:<你的AWD_ID>:function:forgot-vlog-password"
  payload_format_version = "2.0"
}

resource "aws_apigatewayv2_integration" "convert_mov_to_mp4" {
  api_id                 = aws_apigatewayv2_api.vlog_api.id
  integration_type       = "AWS_PROXY"
  integration_uri        = "arn:aws:lambda:ap-northeast-1:<你的AWD_ID>:function:convert-vlog-mov-to-mp4"
  payload_format_version = "2.0"
}

resource "aws_apigatewayv2_integration" "delete_video" {
  api_id                 = aws_apigatewayv2_api.vlog_api.id
  integration_type       = "AWS_PROXY"
  integration_uri        = "arn:aws:lambda:ap-northeast-1:<你的AWD_ID>:function:delete-vlog-video"
  payload_format_version = "2.0"
}

resource "aws_apigatewayv2_integration" "generate_url" {
  api_id                 = aws_apigatewayv2_api.vlog_api.id
  integration_type       = "AWS_PROXY"
  integration_uri        = "arn:aws:lambda:ap-northeast-1:<你的AWD_ID>:function:generate-vlog-s3-presigned-url"
  payload_format_version = "2.0"
}

####################################
# ✅ Route 映射設定
####################################
resource "aws_apigatewayv2_route" "list_videos" {
  api_id    = aws_apigatewayv2_api.vlog_api.id
  route_key = "ANY /list-videos"
  target    = "integrations/${aws_apigatewayv2_integration.list_videos.id}"
}

resource "aws_apigatewayv2_route" "generate_subtitle" {
  api_id    = aws_apigatewayv2_api.vlog_api.id
  route_key = "ANY /generate-subtitle"
  target    = "integrations/${aws_apigatewayv2_integration.generate_subtitle.id}"
}

resource "aws_apigatewayv2_route" "register_member" {
  api_id    = aws_apigatewayv2_api.vlog_api.id
  route_key = "ANY /register"
  target    = "integrations/${aws_apigatewayv2_integration.register_member.id}"
}

resource "aws_apigatewayv2_route" "login_member" {
  api_id    = aws_apigatewayv2_api.vlog_api.id
  route_key = "POST /login"
  target    = "integrations/${aws_apigatewayv2_integration.login_member.id}"
}

resource "aws_apigatewayv2_route" "verify_email" {
  api_id    = aws_apigatewayv2_api.vlog_api.id
  route_key = "ANY /verify-email"
  target    = "integrations/${aws_apigatewayv2_integration.verify_email.id}"
}

resource "aws_apigatewayv2_route" "forgot_password" {
  api_id    = aws_apigatewayv2_api.vlog_api.id
  route_key = "ANY /forgot-password"
  target    = "integrations/${aws_apigatewayv2_integration.forgot_password.id}"
}

resource "aws_apigatewayv2_route" "reset_password" {
  api_id    = aws_apigatewayv2_api.vlog_api.id
  route_key = "ANY /reset-password"
  target    = "integrations/${aws_apigatewayv2_integration.reset_password.id}"
}

resource "aws_apigatewayv2_route" "convert_mov_to_mp4" {
  api_id    = aws_apigatewayv2_api.vlog_api.id
  route_key = "ANY /convert-mov-to-mp4"
  target    = "integrations/${aws_apigatewayv2_integration.convert_mov_to_mp4.id}"
}

resource "aws_apigatewayv2_route" "delete_video" {
  api_id    = aws_apigatewayv2_api.vlog_api.id
  route_key = "ANY /delete-video"
  target    = "integrations/${aws_apigatewayv2_integration.delete_video.id}"
}

resource "aws_apigatewayv2_route" "generate_url" {
  api_id    = aws_apigatewayv2_api.vlog_api.id
  route_key = "ANY /generate-url"
  target    = "integrations/${aws_apigatewayv2_integration.generate_url.id}"
}

# 🔹 API 部署
resource "aws_apigatewayv2_stage" "prod" {
  api_id      = aws_apigatewayv2_api.vlog_api.id
  name        = "prod"
  auto_deploy = true
}

# 🔹 允許 API Gateway 呼叫 Lambda
#resource "aws_lambda_permission" "apigw_invoke" {
#  statement_id  = "AllowAPIGatewayInvoke"
#  action        = "lambda:InvokeFunction"
#  function_name = aws_lambda_function.list_vlog_videos.function_name
#  principal     = "apigateway.amazonaws.com"
#  source_arn    = "${aws_apigatewayv2_api.vlog_api.execution_arn}/*/*"
#}

output "api_endpoint" {
  value = aws_apigatewayv2_stage.prod.invoke_url
}
s

Import 他們!

terraform import aws_apigatewayv2_integration.list_videos iwlw3i3ys4/9804ssj
terraform import aws_apigatewayv2_route.list_videos iwlw3i3ys4/v0xhl3v

terraform import aws_apigatewayv2_integration.generate_subtitle iwlw3i3ys4/61f7rhi
terraform import aws_apigatewayv2_route.generate_subtitle iwlw3i3ys4/3w1zksi

terraform import aws_apigatewayv2_integration.register_member iwlw3i3ys4/aukb6gm
terraform import aws_apigatewayv2_route.register_member iwlw3i3ys4/6yvrgw8

terraform import aws_apigatewayv2_integration.login_member iwlw3i3ys4/a1zfsfc
terraform import aws_apigatewayv2_route.login_member iwlw3i3ys4/c8knbva

terraform import aws_apigatewayv2_integration.verify_email iwlw3i3ys4/lp5cg47
terraform import aws_apigatewayv2_route.verify_email iwlw3i3ys4/6ipuix8

terraform import aws_apigatewayv2_integration.reset_password iwlw3i3ys4/eycavyc
terraform import aws_apigatewayv2_route.reset_password iwlw3i3ys4/r6orxqr

terraform import aws_apigatewayv2_integration.forgot_password iwlw3i3ys4/3r138kq
terraform import aws_apigatewayv2_route.forgot_password iwlw3i3ys4/69zs0d3

terraform import aws_apigatewayv2_integration.convert_mov_to_mp4 iwlw3i3ys4/dm3ly76
terraform import aws_apigatewayv2_route.convert_mov_to_mp4 iwlw3i3ys4/im5rhy3

terraform import aws_apigatewayv2_integration.delete_video iwlw3i3ys4/06oofh4
terraform import aws_apigatewayv2_route.delete_video iwlw3i3ys4/aujel9k

terraform import aws_apigatewayv2_integration.generate_url iwlw3i3ys4/xjq72ut
terraform import aws_apigatewayv2_route.generate_url iwlw3i3ys4/cnc53jm

  • 驗證 import 後的狀態
❯ terraform state list
aws_apigatewayv2_api.vlog_api
aws_apigatewayv2_integration.convert_mov_to_mp4
aws_apigatewayv2_integration.delete_video
aws_apigatewayv2_integration.forgot_password
aws_apigatewayv2_integration.generate_subtitle
aws_apigatewayv2_integration.generate_url
aws_apigatewayv2_integration.list_videos
aws_apigatewayv2_integration.login_member
aws_apigatewayv2_integration.register_member
aws_apigatewayv2_integration.reset_password
aws_apigatewayv2_integration.verify_email
aws_apigatewayv2_route.convert_mov_to_mp4
aws_apigatewayv2_route.delete_video
aws_apigatewayv2_route.forgot_password
aws_apigatewayv2_route.generate_subtitle
aws_apigatewayv2_route.generate_url
aws_apigatewayv2_route.list_videos
aws_apigatewayv2_route.login_member
aws_apigatewayv2_route.register_member
aws_apigatewayv2_route.reset_password
aws_apigatewayv2_route.verify_email
aws_apigatewayv2_stage.prod
aws_iam_role.lambda_exec
aws_iam_role_policy.lambda_policy
  • 寫入計劃
terraform plan

最終套用

❯ terraform apply
aws_apigatewayv2_api.vlog_api: Refreshing state... [id=iwlw3i3ys4]
aws_iam_role.lambda_exec: Refreshing state... [id=lambda-execution-role]
aws_apigatewayv2_integration.generate_subtitle: Refreshing state... [id=61f7rhi]
aws_apigatewayv2_integration.generate_url: Refreshing state... [id=xjq72ut]
aws_apigatewayv2_integration.login_member: Refreshing state... [id=a1zfsfc]
aws_apigatewayv2_integration.list_videos: Refreshing state... [id=9804ssj]
aws_apigatewayv2_integration.verify_email: Refreshing state... [id=lp5cg47]
aws_apigatewayv2_integration.register_member: Refreshing state... [id=aukb6gm]
aws_apigatewayv2_integration.delete_video: Refreshing state... [id=06oofh4]
aws_apigatewayv2_stage.prod: Refreshing state... [id=prod]
aws_apigatewayv2_integration.reset_password: Refreshing state... [id=eycavyc]
aws_apigatewayv2_integration.convert_mov_to_mp4: Refreshing state... [id=dm3ly76]
aws_apigatewayv2_integration.forgot_password: Refreshing state... [id=3r138kq]
aws_apigatewayv2_route.register_member: Refreshing state... [id=6yvrgw8]
aws_apigatewayv2_route.list_videos: Refreshing state... [id=v0xhl3v]
aws_apigatewayv2_route.verify_email: Refreshing state... [id=6ipuix8]
aws_apigatewayv2_route.reset_password: Refreshing state... [id=r6orxqr]
aws_apigatewayv2_route.generate_url: Refreshing state... [id=cnc53jm]
aws_apigatewayv2_route.delete_video: Refreshing state... [id=aujel9k]
aws_apigatewayv2_route.generate_subtitle: Refreshing state... [id=3w1zksi]
aws_apigatewayv2_route.convert_mov_to_mp4: Refreshing state... [id=im5rhy3]
aws_apigatewayv2_route.forgot_password: Refreshing state... [id=69zs0d3]
aws_iam_role_policy.lambda_policy: Refreshing state... [id=lambda-execution-role:lambda-execution-policy]
aws_apigatewayv2_route.login_member: Refreshing state... [id=c8knbva]

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

api_endpoint = "https://iwlw3i3ys4.execute-api.ap-northeast-1.amazonaws.com/prod"

結論

  • 目前因為有大幅更動管理的方法,所以文章的呈現有點凌亂,我後續更新完成後再來調整文字。
  • 今年依舊是寫兩個題目,以為錯開開賽日期,就可以養成習慣穩定輸出,殊不知身體還是會感覺到非常勞累,快要招架不住了,這個連假暫時可以去喘口氣了!

上一篇
【Day 29】 使用 Terraform 集中管理 Amazon Lambda Function 原始碼
系列文
無法成為片師也想拍 Vlog?!個人影音小工具的誕生!30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言